package org.jheuristics.ga.operators.selectors;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.jheuristics.Individual;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.multiObjective.NormalizeFitness;

public class VarianceSelector extends AbstractNormalizeFitnessSelector {

	public VarianceSelector(NormalizeFitness normalizeFitness) {
		super(normalizeFitness);
	}

	@Override
	protected Individual[] select(Individual[] individuals, int howMany, GAStatus status, GAConfig config) {
		double[][] normalizados = getNormalizeFitness().getNormalizedFitness(individuals, status, config);

		// ordenando
		List<Values> valores = new ArrayList<Values>(normalizados.length);
		for (int i = 0; i < normalizados.length; i++) {
			double mean = 0.0;
			for (int j = 0; j < normalizados[i].length; j++) {
				mean += normalizados[i][j];
			}
			mean /= normalizados[i].length;
			double variancia = 0.0;
			for (int j = 0; j < normalizados[i].length; j++) {
				variancia += Math.pow(normalizados[i][j] - mean, 2);
			}
			valores.add(new Values(i, variancia/(normalizados[i].length-1)));
		}
		Collections.sort(valores);

		// selecionando
		List<Values> selected = valores.subList(0, howMany);
		List<Individual> result = new LinkedList<Individual>();
		for (Values selecionado : selected) {
			result.add(individuals[selecionado.index]);
		}
		return result.toArray(new Individual[0]);
	}

	private class Values implements Comparable<Values> {
		Integer index;
		Double value;

		public Values(int index, double value) {
			this.index = index;
			this.value = value;
		}

		public int compareTo(Values o) {
			return value.compareTo(o.value);
		}

		public String toString() {
			return index + ":" + value;
		}

	}

}
